package info.niwota.webshot;

import info.niwota.dnd.DragController;
import info.niwota.dnd.DragLayer;
import info.niwota.dnd.DragSource;
import info.niwota.webshot.bm.BookmarksActivity;
import info.niwota.webshot.image.CropImageActivity;
import info.niwota.webshot.imglist.MultiSelectImageActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URISyntaxException;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Picture;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.PaintDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Message;
import android.provider.Browser;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.Window;
import android.webkit.CookieSyncManager;
import android.webkit.HttpAuthHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebIconDatabase;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;

/**
 * 
 * @author qiangli
 * 
 */
public class WebBaseActivity extends Activity implements OnClickListener,
		DragSource, DragController.DragListener, OnLongClickListener {
	private class CaptureTask extends AsyncTask<Void, Void, Integer> {
		private Throwable error;
		
		@Override
		protected void onCancelled() {
			try {
				dismissDialog(DIALOG_PROGRESS);
			} catch (Exception e) {
				if (Debug.DEBUG) {
					e.printStackTrace();
				}
			}
		}

		@Override
		protected void onPostExecute(Integer result) {
			try {
				postSnapshot();
				//
				dismissDialog(DIALOG_PROGRESS);
			} catch (Exception e) {
				if (Debug.DEBUG) {
					e.printStackTrace();
				}
			}
			if (error != null) {
				showError(error);
			}
		}

		@Override
		protected void onPreExecute() {
			imagefile = null;
			error = null;
			try {
				showDialog(DIALOG_PROGRESS);
			} catch (Exception e) {
				if (Debug.DEBUG) {
					e.printStackTrace();
				}
			}
		}

		@Override
		protected Integer doInBackground(Void... params) {
			try {
				//
				File f = bgSnapshot();
				imagefile = f;
			} catch (Throwable e) {
				error = e;
				//
				if (Debug.DEBUG) {
					e.printStackTrace();
				}
			}
			return null;
		}

	}

	final private class GoDialog extends Dialog {
		public GoDialog(Context ctx) {
			super(ctx, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
			
			setContentView(R.layout.go);
			//
			final EditText txtUrl = (EditText) findViewById(R.id.goto_url);
			final Button btnGo = (Button) findViewById(R.id.goto_button);
			View.OnClickListener l = new View.OnClickListener() {
				public void onClick(View v) {
					String s = txtUrl.getText().toString();
					dismiss();
					doGoto(s);
				}
			};
			btnGo.setOnClickListener(l);
		}

		@Override
		public void cancel() {
			showOrHideCaptureButton();
			super.cancel();
		}
	}

	final private class MyWebChromeClient extends WebChromeClient {

		@Override
		public void onProgressChanged(WebView view, int newProgress) {
			getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
					newProgress * 100);
			if (newProgress == 100) {
				CookieSyncManager.getInstance().sync();
			}
		}

		@Override
		public void onReceivedIcon(WebView view, Bitmap icon) {
			try {
				setFavicon(icon);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onReceivedTitle(WebView view, String title) {
			setTitle(title);
		}
	}

	public static final int BOOKMARK_PAGE_SIZE = 10;

	final class MyWebViewClient extends WebViewClient {

		@Override
		public void onPageStarted(WebView view, String url, Bitmap favicon) {
			super.onPageStarted(view, url, favicon);
			//
			setFavicon(favicon);
		}

		@Override
		public void doUpdateVisitedHistory(WebView view, String url,
				boolean isReload) {
			if (Debug.DEBUG) {
				Log.d(TAG, "doUpdateVisitedHistory reload: " + isReload
						+ " url: " + Utils.truncate(url, 64));
			}
			if (!isHttp(url)) {
				if (Debug.DEBUG) {
					Log.d(TAG, "doUpdateVisitedHistory url discarded");
				}
				return;
			}
			Browser.updateVisitedHistory(getContentResolver(), url, true);
			WebIconDatabase.getInstance().retainIconForPageUrl(url);
			
			//
			showOrHideNaviBar();
		}

		@Override
		public void onPageFinished(WebView view, String url) {
			super.onPageFinished(view, url);
		}

		@Override
		public void onReceivedHttpAuthRequest(WebView view,
				HttpAuthHandler handler, String host, String realm) {
			// TODO integrate with pasta
			super.onReceivedHttpAuthRequest(view, handler, host, realm);
		}

		@Override
		public void onFormResubmission(WebView view, final Message dontResend,
				final Message resend) {
			new AlertDialog.Builder(WebBaseActivity.this).setTitle(
					R.string.dia_resubmit)
					.setMessage(R.string.dia_resubmit_msg).setPositiveButton(
							R.string.action_ok,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									resend.sendToTarget();
								}
							}).setNegativeButton(R.string.action_cancel,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									dontResend.sendToTarget();
								}
							}).setOnCancelListener(new OnCancelListener() {
						public void onCancel(DialogInterface dialog) {
							dontResend.sendToTarget();
						}
					}).show();
		}

		@Override
		public void onTooManyRedirects(WebView view, final Message cancelMsg,
				final Message continueMsg) {
			new AlertDialog.Builder(WebBaseActivity.this).setTitle(
					R.string.dia_redirect)
					.setMessage(R.string.dia_redirect_msg).setPositiveButton(
							R.string.action_ok,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									continueMsg.sendToTarget();
								}
							}).setNegativeButton(R.string.action_cancel,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									cancelMsg.sendToTarget();
								}
							}).setOnCancelListener(new OnCancelListener() {
						public void onCancel(DialogInterface dialog) {
							cancelMsg.sendToTarget();
						}
					}).show();
		}

		@Override
		public boolean shouldOverrideUrlLoading(WebView view, final String url) {
			if (Debug.DEBUG) {
				Log.d(TAG, "shouldOverrideUrlLoading url: " + url);
			}
			try {
				if (url.startsWith(SCHEME_WTAI)) {
					// wtai://wp/mc;number
					// number=string(phone-number)
					if (url.startsWith(SCHEME_WTAI_MC)) {
						Intent intent = new Intent(Intent.ACTION_VIEW, Uri
								.parse(WebView.SCHEME_TEL
										+ url
												.substring(SCHEME_WTAI_MC
														.length())));
						startActivity(intent);
						return true;
					}
					return false;
				}
				if (url.startsWith("about:")) {
					return false;
				}
				//
				final Uri uri = Uri.parse(url);
				final String scheme = uri.getScheme();
				//
				if ("market".equals(scheme)) {
					Intent i = new Intent(Intent.ACTION_VIEW, uri);
					startActivity(i);
					return true;
				}
				if (Bookmarks.SCHEME.equals(scheme)) {
					if (Debug.DEBUG) {
						Log.d(TAG, "shouldOverrideUrlLoading bookmark " + uri);
					}
					final String path = uri.getPath();
					//
					if ("/bin/manage".equals(path)) {
						doManageBookmarks();
						return true;
					}
					//
					doListBookmark(url);
					return true;
				}
				//
				if ("webshot".equals(scheme)) {
					// all
					doViewArchive();
					return true;
					// final File dir = SDCard.getWebshotDir();
					// final String mimetype = "vnd.android.cursor.dir/image";
					// final String bid = ImageUtils.getBucketId(dir.getPath());
					// final Uri wsuri = Uri.parse(dir.toURI().toString())
					// .buildUpon().appendQueryParameter("bucketId", bid)
					// .build();
					// viewImage(wsuri, mimetype);
				}
				//
				if (History.SCHEME.equals(scheme)) {
					int steps = toInt(uri.getQueryParameter("steps"), 0);
					if (Debug.DEBUG) {
						Log.d(TAG, "shouldOverrideUrlLoading history steps: "
								+ steps + " uri: " + uri);
					}
					webview.goBackOrForward(steps);
					return true;
				}
				//
				Intent intent = null;
				try {
					intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
				} catch (URISyntaxException ex) {
					Log.d(TAG, "Bad URI " + url + ": " + ex.getMessage());
					return false;
				}
				if (getPackageManager().resolveActivity(intent, 0) == null) {
					String packagename = intent.getPackage();
					if (packagename != null) {
						intent = new Intent(Intent.ACTION_VIEW,
								Uri.parse("market://search?q=pname:"
										+ packagename));
						intent.addCategory(Intent.CATEGORY_BROWSABLE);
						startActivity(intent);
						return true;
					} else {
						return false;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return false;
		}
	}

	protected static final int DIALOG_GOTO = 10;
	protected static final int DIALOG_PROGRESS = 11;

	public static final int MENU_BACK = R.id.browser_back_opt_menu_id;
	public static final int MENU_BOOKMARK = R.id.browser_bookmark_opt_menu_id;
	public static final int MENU_BROWSE = R.id.browser_browse_opt_menu_id;
	public static final int MENU_PASTA = R.id.browser_pasta_opt_menu_id;

	public static final int MENU_FORWARD = R.id.browser_forward_opt_menu_id;

	public static final int MENU_GOTO = R.id.browser_goto_opt_menu_id;

	public static final int MENU_HOME = R.id.browser_home_opt_menu_id;
	public static final int MENU_QUIT = R.id.browser_quit_opt_menu_id;
	public static final int MENU_REFRESH = R.id.browser_refresh_opt_menu_id;
	public static final int MENU_STOP = R.id.browser_stop_opt_menu_id;
	public static final int MENU_SETTING = R.id.browser_settings_opt_menu_id;
	public static final int MENU_CAPTURE = R.id.browser_capture_opt_menu_id;
	public static final int MENU_CAPTURED = R.id.browser_captured_opt_menu_id;

	private static final int RC_SHARE = 10;

	/* package */final static String SCHEME_WTAI = "wtai://wp/";

	/* package */final static String SCHEME_WTAI_MC = "wtai://wp/mc;";

	private static final String TAG = "WebSnapshotActivity";

	private static final int RC_VIEW_IMAGE = 11;

	private static final int RC_CROP = 12;

	private static final int RC_SETTINGS = 13;

	/**
	 * check if the url is HTTP or HTTPS scheme
	 * 
	 * @param url
	 * @return
	 */
	private static boolean isHttp(String url) {
		if (url == null) {
			return false;
		}
		return (url.startsWith("http") || url.startsWith("https"));
	}

	private static int toInt(String s, int def) {
		try {
			return Integer.parseInt(s);
		} catch (Exception e) {
			// e.printStackTrace();
		}
		return def;
	}
	
	protected void doListBookmark(String url) {
		final Uri uri = Uri.parse(url);
		final String path = uri.getPath();
		final int offset = toInt(uri.getQueryParameter("offset"), 0);
		final int max = toInt(uri.getQueryParameter("max"),
				BOOKMARK_PAGE_SIZE);
		final String data = Bookmarks.load(WebBaseActivity.this,
				path, offset, max);
		webview.loadDataWithBaseURL(url, data, "text/html",
				"UTF-8", null);
	}

	protected void doManageBookmarks() {
		Intent i = new Intent(this, BookmarksActivity.class);
		startActivity(i);
	}

	protected MenuItem backMenuItem;
	protected MenuItem bookmarkMenuItem;
	protected MenuItem browseMenuItem;
	
	protected MenuItem capturedMenuItem;
	protected MenuItem settingsMenuItem;

	protected Button btnAccept; // add to EZ Boarding
	protected Button btnDiscard;
	protected Button btnSave;
	protected Button btnShare;
	protected ImageButton btnSnapshot;
	protected MenuItem forwardMenuItem;
	protected View frameSnapshot;
	protected View frameWeb;
	protected MenuItem gotoMenuItem;
	protected MenuItem homeMenuItem;

	private static final String HOME_URI = "file:///android_asset/index.html";

	protected File imagefile;
	
	protected ImageView imageview;
	protected MenuItem quitMenuItem;
	protected MenuItem refreshMenuItem;
	protected MenuItem pastaMenuItem;

	protected MenuItem stopMenuItem;

	protected WebView webview;

	protected String title;

	protected ImageButton btnCrop;

	protected boolean backQuit;
	private DragLayer frames;
	private int lastX;
	private int lastY;
	private boolean showCaptureButton;
	private int maxWidth;
	private int maxHeight;
	
	protected boolean showNaviBar;
	protected View navibar;
	protected ImageButton btnNaviBack1;
	protected ImageButton btnNaviBack2;
	protected ImageButton btnNaviBack3;
	
	protected boolean fullscreenMode;
	protected boolean enableZoomVol;
	
	protected void doAccept() {
	}

	protected void doDiscard() {
		//
		showWeb();
		//
		if (hasSnapshot()) {
			imagefile.delete();
		}
	}

	protected void doViewArchive() {
		try {
			Intent i = new Intent(this, MultiSelectImageActivity.class);
			i.setAction(Intent.ACTION_VIEW);
			final File dir = SDCard.getWebshotDir();
			Uri data = Uri.parse(dir.toURI().toString());
			i.setData(data);
			startActivity(i);
		} catch (Exception e) {
			showError(e);
		}
	}

	protected void doGoto(String s) {
		try {
			String url = Utils.toUri(s);
			load(url);
		} catch (Exception e) {
			showError(e);
		}
	}

	protected void doQuit() {
		if (Debug.DEBUG) {
			Log.d(TAG, "doQuit");
		}
		try {
			webview.stopLoading();
			//
			setResult(RESULT_CANCELED);
			finish();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doSave() {
		showWeb();
		if (hasSnapshot()) {
			addImage();
			String msg = getString(R.string.text_saved, imagefile.getPath());
			Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
		}
	}

	protected void addImage() {
		ImageUtils.addImage(getContentResolver(), imagefile, title);
	}

	protected void doShare() {
		try {
			if (hasSnapshot()) {
				String subject = title;
				String body = title;
				Uri uri = Uri.parse(imagefile.toURI().toString());
				Intent i = Utils.toShareIntent(subject, body, uri);
				Intent si = Intent.createChooser(i,
						getText(R.string.text_share));
				startActivityForResult(si, RC_SHARE);
				//
				addImage();
			}
		} catch (Exception e) {
			showError(e);
		}
	}

	protected void doSnapshot() {
		CaptureTask t = new CaptureTask();
		t.execute();
	}

	private void postSnapshot() {
		File f = imagefile;
		if (f == null) {
			try {
				imageview.setImageResource(R.drawable.android_headstand);
			} catch (Error e) {
				if (Debug.DEBUG) {
					e.printStackTrace();
				}
			}
		}
		//
		try {
			showSnapshot();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doViewImage() {
	}

	private boolean hasSnapshot() {
		return (imagefile != null && imagefile.exists());
	}

	private File getOutputFile(String fileExt) {
		if (!SDCard.checkSDCard()) {
			return null;
		}
		//
		String name = Utils.createName(webview.getUrl());
		if (name == null) {
			name = Utils.createName(); // date
		}
		//
		File dir = SDCard.getWebshotDir();
		File f = new File(dir, name + fileExt);
		File uf = Utils.findUniqueFile(f);
		if (Debug.DEBUG) {
			Log.d(TAG, "getOutputFile: " + uf);
		}
		return uf;
	}

	protected void goHome() {
		// clear history
		webview.clearHistory();

		showOrHideNaviBar();
		//
		load(HOME_URI);
	}

	protected void init(Bundle b) {
		try {
			backQuit = false;
			
			initSettings();
			//
			showWeb();
			//
			Intent i = getIntent();
			Uri uri = i.getData();
			if (Debug.DEBUG) {
				Log.d(TAG, "uri: " + uri);
			}
			if (uri != null) {
				backQuit = true;
				load(uri.toString());
				return;
			}
			//
			String act = i.getAction();
			if (Debug.DEBUG) {
				Log.d(TAG, "action: " + act + " : " + i.getExtras());
			}
			if (Intent.ACTION_SEND.equals(act)) {
				// via web link/page
				String txt = i.getStringExtra(Intent.EXTRA_TEXT);
				if (txt != null) {
					backQuit = true;
					doGoto(txt);
					return;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// no content
		goHome();
	}

	protected void initRes(Bundle savedInstanceState) {
		frames = (DragLayer) findViewById(R.id.webview_frames);

		frameWeb = findViewById(R.id.webview_frame_web);

		webview = (WebView) findViewById(R.id.webview_page);

		btnSnapshot = (ImageButton) findViewById(R.id.webview_snapshot);
		btnCrop = (ImageButton) findViewById(R.id.webview_crop);
		
		btnSnapshot.setVisibility(View.GONE);
		btnSnapshot.setOnClickListener(this);
		btnCrop.setVisibility(View.VISIBLE);
		btnCrop.setOnClickListener(this);
		//
		frameSnapshot = findViewById(R.id.webview_frame_snapshot);

		imageview = (ImageView) findViewById(R.id.webview_image);
		
		btnSave = (Button) findViewById(R.id.webview_save);
		btnDiscard = (Button) findViewById(R.id.webview_discard);
		btnSave.setVisibility(View.VISIBLE);
		btnDiscard.setVisibility(View.VISIBLE);
		btnSave.setOnClickListener(this);
		btnDiscard.setOnClickListener(this);
		//
		imageview.setOnClickListener(this);
		btnSnapshot.setOnLongClickListener(this);
		frames.setDragListener(this);
		
		//
		btnShare = (Button) findViewById(R.id.webview_share);
		btnAccept = (Button) findViewById(R.id.webview_accept);
		btnShare.setVisibility(View.VISIBLE);
		btnAccept.setVisibility(View.VISIBLE);
		btnShare.setOnClickListener(this);
		btnAccept.setOnClickListener(this);
		
		//navigation
		navibar = findViewById(R.id.webview_navibar);
		btnNaviBack1 = (ImageButton) findViewById(R.id.webview_navi_back1);
		btnNaviBack2 = (ImageButton) findViewById(R.id.webview_navi_back2);
		btnNaviBack3 = (ImageButton) findViewById(R.id.webview_navi_back3);
		
		btnNaviBack1.setOnClickListener(this);
		btnNaviBack2.setOnClickListener(this);
		btnNaviBack3.setOnClickListener(this);
	}

	protected void initWebview(Bundle savedInstanceState) {
		WebSettings s = webview.getSettings();

		s.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
		s.setUseWideViewPort(true);
		s.setSavePassword(false);
		s.setSaveFormData(false);
		s.setSupportZoom(true);
		s.setBuiltInZoomControls(true);
		s.setBlockNetworkImage(false);
		s.setLightTouchEnabled(true);
		//
		s.setJavaScriptEnabled(true);
		//
		webview.setWebChromeClient(new MyWebChromeClient());
		webview.setWebViewClient(new MyWebViewClient());
	}

	protected void load(String url) {
		try {
			
			webview.loadUrl(url);
			//
			showOrHideCaptureButton();
		} catch (Exception e) {
			showError(e);
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (Debug.DEBUG) {
			Log.d(TAG, "onActivityResult requestCode: " + requestCode
					+ " resultCode: " + resultCode + " data: " + data);
		}
		if (requestCode == RC_VIEW_IMAGE) {
			return;
		}
		if (requestCode == RC_SETTINGS) {
			return;
		}
		if (requestCode == RC_CROP) {
			doPostCrop(resultCode, data);
			return;
		}
		//
		showWeb();
	}

	protected void doPostCrop(int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			Bitmap bm = ImageUtils.getImageBitmap(data.getData());
			imageview.setImageBitmap(bm);
		}
	}

	public void onClick(View v) {
		int id = v.getId();
		if (Debug.DEBUG) {
			Log.d(TAG, "onClick id: " + id);
		}
		switch (id) {
		case R.id.webview_snapshot:
			doSnapshot();
			break;
		case R.id.webview_accept:
			doAccept();
			break;
		case R.id.webview_discard:
			doDiscard();
			break;
		case R.id.webview_share:
			doShare();
			break;
		case R.id.webview_save:
			doSave();
			break;
		case R.id.webview_image:
			doViewImage();
			break;
		case R.id.webview_crop:
			doCrop();
			break;
		case R.id.webview_navi_back1:
			goBack(1);
			break;
		case R.id.webview_navi_back2:
			goBack(2);
			break;
		case R.id.webview_navi_back3:
			goBack(3);
			break;
		default:
		}
	}

	protected void goBack(int step) {
		if (!webview.canGoBack()) {
			return;
		}
		switch(step) {
		case 1:
			webview.goBack();
			break;
		case 2:
			webview.goBackOrForward(-2);
			break;
		case 3:
			doBack();
			break;
		default:
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	private void setMaxScreenSize() {
		try {
			Display d = getWindowManager().getDefaultDisplay();
			maxWidth = d.getWidth();
			maxHeight = d.getHeight();
			if (Debug.DEBUG) {
				Log.d(TAG, "setMaxScreenSize display max: " + maxWidth + ":" + maxHeight);
			}
		} catch (Exception e) {
			maxWidth = 320;
			maxHeight = 480;
			//
			e.printStackTrace();
		}
		if (Debug.DEBUG) {
			Log.d(TAG, "setMaxScreenSize final max: " + maxWidth + ":" + maxHeight);
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_GOTO:
			return new GoDialog(this);
		case DIALOG_PROGRESS:
			return createProgressDialog();
		default:
		}
		return null;
	}

	private ProgressDialog createProgressDialog() {
		final Context ctx = this;
		ProgressDialog pd = new ProgressDialog(ctx);
		pd.setMessage(ctx.getText(R.string.wait));
		pd.setIndeterminate(true);
		pd.setCancelable(false);
		return pd;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.browser_options, menu);
		//
		refreshMenuItem = menu.findItem(R.id.browser_refresh_opt_menu_id);
		stopMenuItem = menu.findItem(R.id.browser_stop_opt_menu_id);
		homeMenuItem = menu.findItem(R.id.browser_home_opt_menu_id);
		backMenuItem = menu.findItem(R.id.browser_back_opt_menu_id);
		forwardMenuItem = menu.findItem(R.id.browser_forward_opt_menu_id);
		gotoMenuItem = menu.findItem(R.id.browser_goto_opt_menu_id);
		bookmarkMenuItem = menu.findItem(R.id.browser_bookmark_opt_menu_id);
		
		browseMenuItem = menu.findItem(R.id.browser_browse_opt_menu_id);
		
		capturedMenuItem = menu.findItem(R.id.browser_captured_opt_menu_id);
		pastaMenuItem = menu.findItem(R.id.browser_pasta_opt_menu_id);
		settingsMenuItem = menu.findItem(R.id.browser_settings_opt_menu_id);
		
		quitMenuItem = menu.findItem(R.id.browser_quit_opt_menu_id);
		
		return true;
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		webview.destroy();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		switch (id) {
		case MENU_HOME:
			goHome();
			break;
		case MENU_REFRESH:
			reload();
			break;
		case MENU_STOP:
			stopLoading();
			break;
		case MENU_BACK:
			webview.goBack();
			break;
		case MENU_FORWARD:
			webview.goForward();
			break;
		case MENU_GOTO:
			showAddressBar();
			break;
		case MENU_BROWSE:
			Bookmarks.open(this, webview.getTitle(), webview.getUrl());
			break;
		case MENU_BOOKMARK:
			Bookmarks.add(this, webview.getTitle(), webview.getUrl());
			break;
		case MENU_PASTA:
			doPasta();
			break;
		case MENU_QUIT:
			doQuit();
			break;
		case MENU_SETTING:
			doSettings();
			break;
		case MENU_CAPTURE:
			doSnapshot();
			break;
		case MENU_CAPTURED:
			doViewArchive();
			break;
		default:
			return false;
		}
		return true;
	}

	protected void doSettings() {
		try {
			Intent i = new Intent(this, SettingsActivity.class);
			startActivityForResult(i, RC_SETTINGS);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void doPasta() {
		try {
			Intent i = Utils.createPastaIntent();
			startActivity(i);
		} catch (ActivityNotFoundException e) {
			// e.printStackTrace();
			//
			Utils.showDownloadPasta(this);
		} catch (Exception e) {
			showError(e);
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	@Override
	protected void onPrepareDialog(int id, Dialog dialog) {
		super.onPrepareDialog(id, dialog);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		// disable if snapshot
		if (frameSnapshot.getVisibility() == View.VISIBLE) {
			return false;
		}
		homeMenuItem.setEnabled(true);
		refreshMenuItem.setEnabled(true);
		stopMenuItem.setEnabled(true);
		gotoMenuItem.setEnabled(true);
		backMenuItem.setEnabled(webview.canGoBack());
		forwardMenuItem.setEnabled(webview.canGoForward());
		//
		try {
			boolean b = isHttp(webview.getUrl());
			bookmarkMenuItem.setEnabled(b);
			browseMenuItem.setEnabled(b);
		} catch (Exception e) {
			bookmarkMenuItem.setEnabled(false);
			browseMenuItem.setEnabled(false);
		}
		quitMenuItem.setEnabled(true);
		//
		return true;
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		webview.restoreState(savedInstanceState);
	}

	@Override
	protected void onResume() {
		super.onResume();
		//
		CookieSyncManager.getInstance().startSync();
		//
		restoreCaptureButton();
		
		initSettings();
	}

	private void initSettings() {
		final Context ctx = this;
		//
		showNaviBar = Preferences.isShowNaviBar(ctx);
		fullscreenMode = Preferences.isFullscreen(ctx);
		showCaptureButton = Preferences.isShowCaptureButton(ctx);
		enableZoomVol = Preferences.isZoomVol(ctx);
	}

	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		if (Debug.DEBUG) {
			Log.d(TAG, "onWindowFocusChanged hasFocus: " + hasFocus);
		}
		super.onWindowFocusChanged(hasFocus);
		if (hasFocus) {
			checkAndSetScreen();
			
			//
			showOrHideCaptureButton();
			
			//settings change
			showOrHideNaviBar();
		}
	}

	private void restoreCaptureButton() {
		setMaxScreenSize();
		
		//restore capture button defaults
		int[] pos = Preferences.getLastButtonPosition(this);
		lastX = pos[0];
		lastY = pos[1];
		showCaptureButton = Preferences.isShowCaptureButton(this);
		//
		if (Debug.DEBUG) {
			Log.d(TAG, "restoreCaptureButton show: "+showCaptureButton+" x:y " + lastX + ":" + lastY);
		}
	}
	
	@Override
	protected void onSaveInstanceState(Bundle outState) {
		webview.saveState(outState);
	}

	@Override
	protected void onStop() {
		super.onStop();

		CookieSyncManager.getInstance().stopSync();
		webview.stopLoading();
	}

	private void reload() {
		webview.reload();
	}

	private void setTitle(String title) {
		this.title = title;
		super.setTitle(title);
	}

	private void setFavicon(Bitmap icon) {
		if (icon == null) {
			return;
		}
		Drawable[] array = new Drawable[2];
		PaintDrawable p = new PaintDrawable(Color.WHITE);
		p.setCornerRadius(3f);
		array[0] = p;
		array[1] = new BitmapDrawable(icon);
		//
		LayerDrawable d = new LayerDrawable(array);
		d.setLayerInset(1, 2, 2, 2, 2);
		getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON, d);
	}

	private void showAddressBar() {
		showOrHideCaptureButton();
		showDialog(DIALOG_GOTO);
	}

	protected void showOrHideCaptureButton() {
		boolean b = showCaptureButton;
		btnSnapshot.setVisibility(b ? View.VISIBLE : View.GONE);
		if (b) {
			moveCaptureButton(lastX,lastY);
		}
	}
	
	protected void showOrHideNaviBar() {
		final boolean b = showNaviBar;
		if (Debug.DEBUG) {
			Log.d(TAG, "showOrHideNaviBar show: " + b);
		}
		navibar.setVisibility(b ? View.VISIBLE : View.GONE);
		
		if (b) {
			final boolean b1 = true; //webview.canGoBack();
			final boolean b2 = (b1 && webview.canGoBackOrForward(-2));
			final boolean b3 = (b2 && webview.canGoBackOrForward(-3));
			btnNaviBack1.setVisibility(b1 ? View.VISIBLE : View.GONE);
			btnNaviBack2.setVisibility(b2 ? View.VISIBLE : View.GONE);
			btnNaviBack3.setVisibility(b3 ? View.VISIBLE : View.GONE);
		}	
	}
	
	private void showError(Throwable e) {
		try {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
		} catch (Throwable t) {
			Log.d(TAG, "showError " + t);
		}
	}

	private void showMessage(String s) {
		Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
	}

	protected void showSnapshot() {
		frameWeb.setVisibility(View.GONE);
		frameSnapshot.setVisibility(View.VISIBLE);
		//
		boolean b = (imagefile == null ? false : true);

		btnCrop.setEnabled(b);
		btnCrop.setVisibility(b ? View.VISIBLE : View.GONE);
		
		//
		btnSave.setEnabled(b);
		btnDiscard.setEnabled(true);
		
		btnShare.setEnabled(b);
		btnAccept.setEnabled(b);
	}

	protected void showWeb() {
		frameWeb.setVisibility(View.VISIBLE);
		frameSnapshot.setVisibility(View.GONE);
		
		webview.setClickable(true);
		//
		showOrHideNaviBar();
		//
		showOrHideCaptureButton();
	}

	private Bitmap smartCapture() {
		final Runtime rt = Runtime.getRuntime();
		rt.gc();
		final long free = rt.freeMemory();
		final long avail = (long) (free * 98 / 100); // leave some room ???
		final Picture pic = webview.capturePicture();

		final int width = pic.getWidth();
		final int height = pic.getHeight();
		//
		final int bytes = getBitmapBytes();
		final long required = (width * height * bytes);

		int scaleWidth = width;
		int scaleHeight = height;
		float scale = 1.0f;
		if (required > avail) {
			// need to scale the image
			scale = (float) Math.sqrt((double) avail / (double) required);
			scaleWidth = (int) (width * scale);
			scaleHeight = (int) (height * scale);
		}
		//if too small, don't bother
		final int smallsize = 64;
		if (scaleWidth < smallsize || scaleHeight < smallsize ) {
			return null;
		}
		//
		final Config bc = getBitmapConfig();
		if (Debug.DEBUG) {
			Log.d(TAG, "capture free: " + free + " avail: " + avail
					+ " required: " + required);
			Log.d(TAG, "bytes: " + bytes + " config: " + bc);
			Log.d(TAG, "width: " + width + " height: " + height);
			Log.d(TAG, "scale: " + scale + " scaleWidth: " + scaleWidth
					+ " scaleHeight: " + scaleHeight);
		}
		//
		Bitmap b = Bitmap.createBitmap(scaleWidth, scaleHeight, bc);
		Canvas c = new Canvas(b);
		c.scale(scale, scale);
		pic.draw(c);

		if (Debug.DEBUG) {
			Log.d(TAG, "scaled bitmap width: " + b.getWidth() + " height: "
					+ b.getHeight());
		}
		return b;
	}

	private Bitmap.Config getBitmapConfig() {
		final int c = Preferences.getBitmapConfig(this);
		// not working Bitmap.Config.ALPHA_8
		final Bitmap.Config[] bc = new Bitmap.Config[] { Bitmap.Config.RGB_565,
				Bitmap.Config.ARGB_4444, Bitmap.Config.ARGB_8888 };
		return bc[c];
	}

	private int getBitmapBytes() {
		// mapping in the order of RGB 565, ARGB 4444, ARGB 8888
		final int c = Preferences.getBitmapConfig(this);
		final int[] bytes = new int[] { 2, 2, 4 };
		return bytes[c];
	}

	private File bgSnapshot() throws Throwable {
		final String ext = Preferences.getOutputFormat(this);
		File f = getOutputFile(ext);
		FileOutputStream fos = null;
		Bitmap b = null;
		try {
			// capture
			boolean smart = Preferences.isSmartCapture(this);
			if (smart) {
				b = smartCapture();
			} 
			//not smart or smart aborted
			if (!smart || b == null) {
				// capture as is
				Picture pic = webview.capturePicture();
				final Config bc = getBitmapConfig();
				final int w = pic.getWidth();
				final int h = pic.getHeight();
				if (Debug.DEBUG) {
					Log.d(TAG, "capture as is: width: " + w + " height: " + h
							+ " config: " + bc);
				}
				b = Bitmap.createBitmap(w, h, bc);
				Canvas c = new Canvas(b);
				pic.draw(c);
			}
			//
			if (f != null) {
				fos = new FileOutputStream(f);
			} else {
				// default
				final String name = "snapshot" + ext;
				fos = openFileOutput(name, Context.MODE_WORLD_READABLE);
				f = getFileStreamPath(name);
			}
			if (fos != null) {
				CompressFormat cf = (ext.equals(Preferences.EXT_JPG) ? CompressFormat.JPEG
						: CompressFormat.PNG);
				int q = Preferences.getQuality(this);
				if (Debug.DEBUG) {
					Log.d(TAG, "format: " + cf + " quality: " + q);
				}
				boolean success = b.compress(cf, q, fos);
				if (!success) {
					showMessage(getString(R.string.msg_save_failed));
				}
			}
			//
			imageview.setImageBitmap(b);
			//
			if (Debug.DEBUG) {
				Log.d(TAG, "snapshot saved: " + f);
			}
			return f;
		} catch (Throwable e) {
			imagefile = null;
			if (f != null) {
				f.delete();
			}
			throw e;
			//showError(e);
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		//return null;
	}

	private void stopLoading() {
		webview.stopLoading();
	}

	protected void doCrop() {
		try {
			Intent i = new Intent(this, CropImageActivity.class);
			final Uri uri = Uri.parse(imagefile.toURI().toString());
			if (Debug.DEBUG) {
				Log.d(TAG, "doCrop: " + uri);
			}
			i.setData(uri);
			// overwrite
			i.putExtra(MediaStore.EXTRA_OUTPUT, uri);
			//
			startActivityForResult(i, RC_CROP);
		} catch (Exception e) {
			Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
		}
	}

	public void onDropCompleted(View target, int x, int y, boolean success) {
		Log.d(TAG, " onDropCompleted target: " + target + " x: " + x + " y: "
				+ y + " : " + success);
		lastX = x;
		lastY = y;
	}

	public void setDragger(DragController dragger) {
		//
	}

	public boolean onLongClick(View v) {
		int id = v.getId();
		if (Debug.DEBUG) {
			Log.d(TAG, "onLongClick id: " + id);
		}
		if (id == R.id.webview_snapshot) {
			startDrag(v);
			return true;
		}
		return false;
	}

	private void startDrag(View v) {
		btnSnapshot.setBackgroundResource(R.drawable.btn_round_pressed_bg);
		frames.startDrag(v, this, v.getTag(), DragController.DRAG_ACTION_MOVE);
	}

	public void onDragEnd() {
		int x = lastX;
		int y = lastY;

		moveCaptureButton(x, y);
		//save
		Preferences.putLastButtonPosition(this, x, y);
	}

	private void moveCaptureButton(int x, int y) {
	
		if (Debug.DEBUG) {
			Log.d(TAG, " moveCaptureButton : x:y " + x + ":" + y);
		}
		View v = btnSnapshot;
		View layer = frames;
		RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) v
				.getLayoutParams();
		int mw = Math.min(maxWidth, layer.getWidth() - layer.getLeft());
		int mh = Math.min(maxHeight, layer.getHeight() - layer.getTop());
		mw -= p.width;
		mh -= p.height;
		final int dx = Math.min(x, mw);
		final int dy = Math.min(y, mh);

		if (Debug.DEBUG) {
			Log.d(TAG, " moveCaptureButton : dx:dy " + dx + ":" + dy);
		}

		p.leftMargin = dx;
		p.topMargin = dy;
		//
		v.setBackgroundResource(R.drawable.btn_round_bg);
		//
		v.invalidate();
	}

	public void onDragStart(View v, DragSource source, Object info,
			int dragAction) {
		if (Debug.DEBUG) {
			Log.d(TAG, " onDragStart v: " + v + " source: " + source
					+ " info: " + info + " dragAction: " + dragAction);
		}
	}

	protected void doBack() {
	}

	protected void checkAndSetScreen() {
		//getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
		final Window w = getWindow();
	
		if (fullscreenMode) {
			w.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
			w.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
		} else {
			w.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
			w.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		}
	}
}
